'use strict';
class DynamicCursor {
    static defaultOpt = {
        size: 18, //默认大小
        expandedSize: 40, //特殊大小
        background: 'rgba(161, 142, 218, 0.4)', //小球背景
        borderWidth: 0, //边框
        borderColor: 'black',
        iconSize: 28, //图标大小
        iconColor: 'white', //图标颜色
        selectColor: '#17BFA3', //选中对象的边框颜色
        triggerElements: []
    };
    cursor = null;
    cursorIcon = null;
    zoomStyle = null;
    configOpt = null;
    isStuck = false;
    LQY = null;
    constructor(option) {
        this.configOpt = {
            ...DynamicCursor.defaultOpt,
            ...option
        };
        this.init();
    }
    init() {
        this.LQY = this.__initLqy();
        this.createDom();
        this.addEvent();
    }
    createDom() {
        this.zoomStyle = document.createElement('link');
        this.zoomStyle.setAttribute('rel', 'stylesheet');
        this.zoomStyle.setAttribute('href', 'https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css');//https://www.ymrlqy.top/support/line-awesome/line-awesome-font-awesome.min.css
        document.head.appendChild(this.zoomStyle);
        this.cursor = document.createElement('div');
        this.cursorIcon = document.createElement('div');
        this.cursorIcon.classList.add('cursorIcon');
        this.cursorIcon.style.position = 'absolute';
        this.cursorIcon.style.fontFamily = 'Raleway';
        this.cursorIcon.style.textTransform = 'uppercase';
        this.cursorIcon.style.fontWeight = '800';
        this.cursorIcon.style.textAlign = 'center';
        this.cursorIcon.style.top = '50%';
        this.cursorIcon.style.width = '100%';
        this.cursorIcon.style.transform = 'translateY(-50%)';
        this.cursorIcon.style.color = this.configOpt.iconColor;
        this.cursorIcon.style.fontSize = this.configOpt.iconSize + 'px';
        this.cursorIcon.style.transition = `opacity ${this.configOpt.expandSpeed}s`;
        this.cursor.classList.add('dynamicCursor');
        this.cursor.style.boxSizing = 'border-box';
        this.cursor.style.width = `${this.configOpt.size}px`;
        this.cursor.style.height = `${this.configOpt.size}px`;
        this.cursor.style.borderRadius = `${this.configOpt.expandedSize}px`;
        this.cursor.style.pointerEvents = 'none';
        this.cursor.style.zIndex = 999;
        this.cursor.style.transition =
            `width .2s linear,height .2s linear,border-radius .2s linear,zIndex 0s linear,transform .2s linear`;
        this.cursor.style.border = `${this.configOpt.borderWidth}px solid ${this.configOpt.borderColor}`;
        this.cursor.style.position = 'fixed';
        this.cursor.style.background = this.configOpt.background;
        this.cursor.appendChild(this.cursorIcon);
        document.body.appendChild(this.cursor);
    }
    addEvent() {
        document.addEventListener('mousemove', e => this.__mousemoveEvent(e));
        document.addEventListener('mouseup', e => this.__mouseupEvent(e));
        document.addEventListener('mousedown', e => this.__mousedownEvent(e));
        for (let i = 0; i < this.configOpt.triggerElements.length; i++) {
            const trigger = this.LQY(`.${this.configOpt.triggerElements[i].className}`);
            const icon = this.configOpt.triggerElements[i].icon ?
                `<i class="${this.configOpt.triggerElements[i].icon}"></i>` : '';
            // this.configOpt.triggerElements[i].iconStr = icon;
            if (trigger) {
                this.__each(trigger, el => {
                    // trigger[el].style.cursor = 'default';
                    trigger[el].addEventListener('mouseover', e => this.__itemmouseoverEvent(e, icon));
                    trigger[el].addEventListener('mouseout', e => this.__itemmouseoutEvent(e));
                });
            }
        }
    }
    remove() {
        document.removeEventListener('mousemove', e => this.__mousemoveEvent(e));
        document.removeEventListener('mouseup', e => this.__mouseupEvent(e));
        document.removeEventListener('mousedown', e => this.__mousedownEvent(e));
        for (let i = 0; i < this.configOpt.triggerElements.length; i++) {
            const trigger = this.LQY(`.${this.configOpt.triggerElements[i].className}`);
            const icon = this.configOpt.triggerElements[i].icon ?
                `<i class="${this.configOpt.triggerElements[i].icon}"></i>` : '';
            // this.configOpt.triggerElements[i].iconStr = icon;
            if (trigger) {
                this.__each(trigger, el => {
                    trigger[el].removeEventListener('mouseover', e => this.__itemmouseoverEvent(e, icon));
                    trigger[el].removeEventListener('mouseout', e => this.__itemmouseoutEvent(e));
                });
            }
        }
        this.cursor.remove();
        this.zoomStyle.remove();
    }
    __mousemoveEvent(e) {
        this.cursor.style.opacity = this.configOpt.opacity;
        this.cursor.style.top = '0';
        this.cursor.style.left = '0';
        if (!this.isStuck) this.cursor.style.transform =
            `translateX(calc(${e.clientX}px - 50%)) translateY(calc(${e.clientY}px - 50%))`;
    }
    __mousedownEvent(e) {
        this.cursor.style.width =
            `${Number(this.cursor.style.width.substring(0,this.cursor.style.width.length-2))+15}px`;
        this.cursor.style.height =
            `${Number(this.cursor.style.height.substring(0,this.cursor.style.height.length-2))+15}px`;
    };
    __mouseupEvent(e) {
        this.cursor.style.width =
            `${Number(this.cursor.style.width.substring(0,this.cursor.style.width.length-2))-15}px`;
        this.cursor.style.height =
            `${Number(this.cursor.style.height.substring(0,this.cursor.style.height.length-2))-15}px`;
    }
    __itemmouseoverEvent(e, icon) {
        console.log('icon', icon);
        if (icon) {
            this.cursor.style.width = `${this.configOpt.expandedSize}px`;
            this.cursor.style.height = `${this.configOpt.expandedSize}px`;
        } else {
            this.isStuck = true;
            const targetBox = (e.currentTarget || e.target).getBoundingClientRect();
            // console.log('targetBox', e, targetBox);
            this.cursor.style.width = `${targetBox.width}px`;
            this.cursor.style.height = `${targetBox.height}px`;
            this.cursor.style.transform =
                `translateX(calc(${targetBox.left + targetBox.width / 2}px - 50%)) translateY(calc(${targetBox.top + targetBox.height / 2}px - 50%))`;
            this.cursor.style.borderRadius = `0px`;
            this.cursor.style.border = `2px solid ${this.configOpt.selectColor}`;
        }
        this.cursorIcon.innerHTML = icon;
    }
    __itemmouseoutEvent(e) {
        this.isStuck = false;
        this.cursor.style.width = `${this.configOpt.size}px`;
        this.cursor.style.height = `${this.configOpt.size}px`;
        this.cursor.style.borderRadius = `${this.configOpt.expandedSize}px`;
        this.cursor.style.border = `${this.configOpt.borderWidth}px solid ${this.configOpt.borderColor}`;
        this.cursorIcon.innerHTML = '';
    }
    __each(object, callback, args) {
        let name,
            i = 0,
            length = object.length;
        if (args) {
            if (length == undefined) {
                for (name in object) {
                    if (callback.apply(object[name], args) === false) {
                        break;
                    }

                }
            } else {
                for (; i < length;) {
                    if (callback.apply(object[i++], args) === false) {
                        break;
                    }
                }
            }
        } else {
            if (length == undefined) {
                for (name in object) {
                    if (callback.call(object[name], name, object[name]) === false) {
                        break;
                    }
                }
            } else {
                for (var value = object[0]; i < length && callback.call(value, i, value) !== false; value = object[
                        ++i]) {};
            }
        }
        return object;
    }
    __initLqy() {
        // Save a reference to core methods
        var slice = Array.prototype.slice;

        // selector regular expression
        var rId = /^#[\w\-]+/;
        var rTag = /^([\w\*]+)$/;
        var rCls = /^([\w\-]+)?\.([\w\-]+)/;
        var rAttr = /^([\w]+)?\[([\w]+-?[\w]+?)(=(\w+))?\]/;

        // For IE9/Firefox/Safari/Chrome/Opera
        var makeArray = function(obj) {
            return slice.call(obj, 0);
        }
        // For IE6/7/8
        try {
            slice.call(document.documentElement.childNodes, 0)[0].nodeType;
        } catch (e) {
            makeArray = function(obj) {
                var result = [];
                for (var i = 0, len = obj.length; i < len; i++) {
                    result[i] = obj[i];
                }
                return result;
            }
        }

        function byId(id) {
            return document.getElementById(id);
        }

        function check(attr, val, node) {
            var reg = RegExp('(?:^|\\s+)' + val + '(?:\\s+|$)');
            var attribute = attr === 'className' ?
                node.className :
                node.getAttribute(attr);
            if (attribute) {
                if (val) {
                    if (reg.test(attribute)) return true;
                } else {
                    return true;
                }
            }
            return false;
        }

        function filter(all, attr, val) {
            var el, result = [];
            var i = 0,
                r = 0;
            while ((el = all[i++])) {
                if (check(attr, val, el)) {
                    result[r++] = el;
                }
            }
            return result;
        }

        function query(selector, context) {
            var s = selector,
                arr = [];
            var context = context === undefined ?
                document :
                typeof context === 'string' ? query(context)[0] : context;

            if (!selector) return arr;

            // id和tagName 直接使用 getElementById 和 getElementsByTagName

            // id
            if (rId.test(s)) {
                arr[0] = byId(s.substr(1, s.length));
                return arr;
            }

            // Tag name
            if (rTag.test(s)) {
                return makeArray(context.getElementsByTagName(s));
            }

            // 优先使用querySelector，现代浏览器都实现它了
            if (context.querySelectorAll) {
                if (context.nodeType === 1) {
                    var old = context.id,
                        id = context.id = '__ZZ__';
                    try {
                        return context.querySelectorAll('#' + id + ' ' + s);
                    } catch (e) {
                        throw new Error('querySelectorAll: ' + e);
                    } finally {
                        old ? context.id = old : context.removeAttribute('id');
                    }
                }
                return makeArray(context.querySelectorAll(s + ''));
            }

            // ClassName
            if (rCls.test(s)) {
                var ary = s.split('.');
                var tag = ary[0];
                var cls = ary[1];
                if (context.getElementsByClassName) {
                    var elems = context.getElementsByClassName(cls);
                    if (tag) {
                        for (var i = 0, len = elems.length; i < len; i++) {
                            var el = elems[i];
                            el.tagName.toLowerCase() === tag && arr.push(el);
                        }
                        return arr;
                    } else {
                        return makeArray(elems);;
                    }
                } else {
                    var all = context.getElementsByTagName(tag || '*');
                    return filter(all, 'className', cls);;
                }
            }

            // Attribute
            if (rAttr.test(s)) {
                var result = rAttr.exec(s);
                var all = context.getElementsByTagName(result[1] || '*');
                return filter(all, result[2], result[4]);
            }
        }
        return query;
    }
}
(()=>{
    "object" == typeof exports && "object" == typeof module ? module.exports = DynamicCursor : "function" ==
        typeof define &&
        define.amd ? define([], DynamicCursor) : "object" == typeof exports ? exports.default = DynamicCursor : window
        .DynamicCursor = DynamicCursor;
})();
// export default DynamicCursor;
